package com.training.hatton.dropboxclient.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;

import com.training.hatton.base.RequestDataWrapper;
import com.training.hatton.dropboxclient.utill.ProcessorCallbackListener;
import com.training.hatton.dropboxclient.utill.ProcessorHelperFactory;

public class ServiceHelper {
	
	public static final String DOWNLOAD_METADATA_BASE_URL = "https://api.dropbox.com/1/metadata/";
	public static final String DELETE_FILE_BASE_URL = "https://api.dropbox.com/1/fileops/delete";
	public static final String DOWNLOAD_FILE_BASE_URL = "https://api-content.dropbox.com/1/files/";

	
	private static final String URL_BUILDER = "{0}{1}{2}?{3}";
	public static final String EXTRA_RESULT_RECEIVER = "result receiver";
	public static final String EXTRA_DATA_REQUEST = "for_request";
	public static final String SERVICE_HELPER = "service helper";
	
	private static final String UTF_8 = "utf-8";
	private static final String[] DELETE_FILE_PARAM_KEYS = new String[] {"root", "path"};
	private static final String[] DOWNLOAD_FILE_PARAM_KEYS = new String[] {"rev"};
	
	private Context mContext;
	private List<RequestDataWrapper> mRequestStorage;
	private List<ProcessorCallbackListener> mListenerStorage;
	private int mIdCounter;
	private ResultReceiver mResultReceiver;
	
	
	public ServiceHelper(Context ctx) {
		mIdCounter = 0;
		mContext = ctx;
		mRequestStorage = new ArrayList<RequestDataWrapper>();
		mListenerStorage = new ArrayList<ProcessorCallbackListener>();
		mResultReceiver = new ResultReceiver(new Handler()){
			@Override
			protected void onReceiveResult(int resultCode, Bundle resultData) {
				onRESTResult(resultCode, resultData);
				super.onReceiveResult(resultCode, resultData);
			}
		};
	}
	
	
	private void startService(RequestDataWrapper dataWrapper){
		for(RequestDataWrapper requestDataWrapper : mRequestStorage){
			if(requestDataWrapper.getUrl().equals(dataWrapper.getUrl())){
				return;
			}
		}
		mRequestStorage.add(dataWrapper);
		Intent intent = new Intent(mContext, RESTService.class);
		intent.putExtra(EXTRA_DATA_REQUEST, dataWrapper.getData());
		intent.putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver);
		mContext.startService(intent);
	}
	
	private void onRESTResult(int resultCode, Bundle resultData) {
		if(resultData!=null){
			RequestDataWrapper dataWrapper = new RequestDataWrapper(resultData.getBundle(EXTRA_DATA_REQUEST));
			for (RequestDataWrapper requestDataWrapper : mRequestStorage) {
				if(requestDataWrapper.getUrl().equals(dataWrapper.getUrl()))
					mRequestStorage.remove(requestDataWrapper);
			}
		}
		if(!mListenerStorage.isEmpty()){
			for (ProcessorCallbackListener listener : mListenerStorage) {
				listener.onResult(resultCode, resultData);
			}
		}
	}
	
	public int downloadFile(String root, String path, String rev){
		String params = buildParams(DOWNLOAD_FILE_PARAM_KEYS, new String[]{rev});
		String url = MessageFormat.format(URL_BUILDER, DOWNLOAD_FILE_BASE_URL, root, path, params);
		int id = createId();
		RequestDataWrapper dataWrapper = boxData(id, ProcessorHelperFactory.DOWNLOAD_FILE_PROCESSOR, url);
		startService(dataWrapper);
		return id;
	}
	
	public int deleteFile(String root, String path){
		String params = buildParams(DELETE_FILE_PARAM_KEYS, new String[]{root, path});
		String url = MessageFormat.format(URL_BUILDER, DELETE_FILE_BASE_URL,"","",params);
		int id = createId();
		RequestDataWrapper dataWrapper = boxData(id, ProcessorHelperFactory.DELETE_FILE_PROCESSOR, url);
		startService(dataWrapper);
		return id;
	}
	
	public int downloadMetadata(String root, String path){
		String url = MessageFormat.format(URL_BUILDER, DOWNLOAD_METADATA_BASE_URL, root, path, "");
		int id = createId(); 
		RequestDataWrapper dataWrapper = boxData(id, ProcessorHelperFactory.DOWNLOAD_METADATA_PROCESSOR, url);
		startService(dataWrapper);
		return id;
	}
	
	private String buildParams(String[] keys, String[] values){
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		for (int i = 0; i < values.length; i++) {
			nameValuePairs.add(new BasicNameValuePair(keys[i], values[i]));
		}
		return URLEncodedUtils.format(nameValuePairs, UTF_8);
	}
	
	private RequestDataWrapper boxData(int id, int processorId, String url){
		RequestDataWrapper dataWrapper = new RequestDataWrapper(); 
		dataWrapper.setId(id);
		dataWrapper.setProcessorId(processorId);
		dataWrapper.setUrl(url.replace(" ", "%20"));
		return dataWrapper;
	}
	
	public static ServiceHelper get(Context ctx){
		ServiceHelper serviceHelper = (ServiceHelper) ctx.getSystemService(SERVICE_HELPER);
	if(serviceHelper != null){
		return serviceHelper;
	}
	serviceHelper = (ServiceHelper) ctx.getApplicationContext().getSystemService(SERVICE_HELPER);
	if(serviceHelper != null){
		return serviceHelper;
	}
	throw new IllegalStateException("Service " + ServiceHelper.class + " is not available");
	}
	
	public void registerProcessorCallbackListener(ProcessorCallbackListener callback){
		mListenerStorage.add(callback);
	}
	
	public void removeProcessorCallbackListener(ProcessorCallbackListener callback){
		mListenerStorage.remove(callback);
	}
	
	private int createId(){
		return mIdCounter++;
	}
}